#pragma once
#pragma warning (disable : 4251 )
#include "Object.h"
#include <boost/intrusive/list.hpp>
#include "ComponentID.h"
#include "util/Shared_ptr.h"


namespace Boon
{

	class ProcessManager;

/*!
* GameComponents represent Objects/Logics that can be added to 
* a GameObject to broaden its logic
*/
class BOON_API GameComponent : public Object
{
	typedef	boost::intrusive::list_member_hook<> MemberHook;

	#pragma region Assignment - Ctor

	GameComponent( const GameComponent& o );
	const GameComponent& operator=( const GameComponent& rhs );

protected:
	GameComponent( const char* compName, Boon::GameObject* g );

	#pragma endregion

public:
	inline GameObject&							GetGameObject() const;
	void										SetEnabled( bool flag );
	inline const bool							IsEnabled() const;
	virtual unsigned int						GetComponentID() const = 0;
	virtual void								Destroy() sealed;

protected:

	virtual void								OnCreate() = 0;
	virtual void								OnEnable() = 0;
	virtual void								OnStart() = 0;
	virtual void								Update() = 0;
	virtual void								LateUpdate() = 0;
	virtual void								OnDisable() = 0;
	virtual void								OnDestroy() = 0;

private:
	// operator used for boost intrusive::list::remove
	friend bool operator==( const GameComponent& lfs, const GameComponent& rhs );

	Boon::GameObject*							m_GameObject; 		/*!< Ptr to the gameobject owning this component */
	MemberHook									m_GO_Member;		/*!< Hook that will be used to store component in updatelist */
	bool										m_Enabled;

	friend class GameObject;
	friend class ProcessManager;
};

}

/*!
* Use this macro to define MUST-HAVE class definitions etc
* in all new created GameComponent-Derivations!
*/
#define GAMECOMPONENT( classname, base ) protected: \
classname( const char* compName, Boon::GameObject* g ) \
: base##( compName, g ){ } \
	\
friend class Boon::GameObject; \
public: \
	\
static const Boon::ComponentID COMPONENT_ID = CID_ ## classname; \
	\
virtual unsigned int GetComponentID() const { return COMPONENT_ID; } \
	\
static const char* GetComponentName() { return #classname ; } \
	\
private: \
	\
static Boon::Shared_ptr<Boon::GameComponent> Create( Boon::GameObject* g ) \
{ \
	return Boon::Shared_ptr<Boon::GameComponent>( new classname##( #classname, g ) );	\
} \


// Implementation of Inline function that should be inlined in all
// calling cpps
const bool Boon::GameComponent::IsEnabled() const {	return m_Enabled; }
